package org.yunai.swjg.server.module.player.operation;

import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.yunai.swjg.server.core.constants.PlayerConstants;
import org.yunai.swjg.server.core.service.Online;
import org.yunai.swjg.server.core.service.OnlineState;
import org.yunai.swjg.server.entity.FormationEntity;
import org.yunai.swjg.server.entity.PlayerEntity;
import org.yunai.swjg.server.module.formation.FormationMapper;
import org.yunai.swjg.server.module.idSequence.IdSequenceHolder;
import org.yunai.swjg.server.module.player.PlayerMapper;
import org.yunai.swjg.server.module.player.SexEnum;
import org.yunai.swjg.server.module.player.VocationEnum;
import org.yunai.swjg.server.module.player.template.VocationTemplate;
import org.yunai.swjg.server.module.player.vo.Player;
import org.yunai.swjg.server.rpc.message.S_C.S_C_PlayerCreateResp;
import org.yunai.yfserver.async.IIoOperation;
import org.yunai.yfserver.async.IIoOperationService;
import org.yunai.yfserver.common.LoggerFactory;
import org.yunai.yfserver.common.constants.CommonErrorLogInfo;
import org.yunai.yfserver.spring.BeanManager;
import org.yunai.yfserver.util.StringUtils;

import java.util.Arrays;

/**
 * 角色创建Io操作
 * User: yunai
 * Date: 13-3-30
 * Time: 下午5:02
 */
public class PlayerCreateOperation implements IIoOperation {

    private static Logger LOGGER = LoggerFactory.getLogger(LoggerFactory.Logger.async, PlayerCreateOperation.class);

    private static PlayerMapper playerMapper;
    private static FormationMapper formationMapper;
    private static IIoOperationService ioOperationService;
    static {
        PlayerCreateOperation.playerMapper = BeanManager.getBean(PlayerMapper.class);
        PlayerCreateOperation.formationMapper = BeanManager.getBean(FormationMapper.class);
        PlayerCreateOperation.ioOperationService = BeanManager.getBean(IIoOperationService.class);
    }

    /**
     * 昵称
     */
    private final String nickname;
    /**
     * 职业编号
     */
    private final Short vocation;
    /**
     * 性别
     */
    private final Short sex;
    /**
     * 在线信息
     */
    private volatile Online online;

    /**
     * 创建角色结果<br />
     * 0 - 创建失败，参数错误<br />
     * 1 - 创建成功<br />
     * 2 - 创建失败，昵称重复<br />
     * 3 - 创建失败，已经创建角色<br />
     */
    private volatile byte createResult = 0;

    public PlayerCreateOperation(Online online, String nickname, Short vocation, Short sex) {
        this.online = online;
        this.nickname = nickname;
        this.vocation = vocation;
        this.sex = sex;
    }

    @Override
    public State doStart() {
        // 检查数据
        if (sex == null || !SexEnum.check(sex)
                || vocation == null || !VocationEnum.check(vocation)) {
            createResult = 0;
            return State.IO_DONE;
        }
        return State.STARTED;
    }

    @Override
    public State doIo() {
        if (online.isConnected()) {
            try {
                // 插入玩家信息
                PlayerEntity playerEntity = new PlayerEntity();
                playerEntity.setId(IdSequenceHolder.genPlayerOrPartnerId());
                playerEntity.setUid(online.getUser().getId());
                playerEntity.setServerId(online.getServerId());
                playerEntity.setNickname(nickname);
                playerEntity.setVocation(vocation);
                playerEntity.setSex(sex);
                playerEntity.setSceneId(PlayerConstants.DEFAULT_SCENE_ID);
                playerEntity.setSceneX(PlayerConstants.DEFAULT_SCENE_X);
                playerEntity.setSceneY(PlayerConstants.DEFAULT_SCENE_Y);
                playerEntity.setScenePreId(Player.SCENE_PRE_ID_NULL);
                playerEntity.setScenePreX(Player.SCENE_PRE_X_NULL);
                playerEntity.setScenePreY(Player.SCENE_PRE_Y_NULL);
                playerEntity.setLevel((short) 1);
                playerEntity.setExp(0);
                playerEntity.setCoin(0);
                playerEntity.setGold(0);
                playerEntity.setReputation(0);
                playerEntity.setSoul(0);
                playerEntity.setLoginTime(0L);
                playerEntity.setLastLoginTime(0L);
                playerEntity.setLastIp("");
                playerEntity.setCreateRoleTime(System.currentTimeMillis());
                playerEntity.setTotalOnlineTime(0L);
                playerEntity.setLastLastLoginTime(0L);
                playerEntity.setLastLastIp("");
                playerEntity.setDevelopStrength(0);
                playerEntity.setDevelopStunt(0);
                playerEntity.setDevelopMagic(0);
                playerEntity.setSpecialSkill(VocationTemplate.get(vocation).getPlayerCreateSkill().getSn());
                playerMapper.insertPlayer(playerEntity);
                // 插入阵形 TODO 暂时这么弄。等阵形逻辑完全理出来，这里在改改。太裸了。
                FormationEntity formationEntity = new FormationEntity();
                formationEntity.setId(playerEntity.getId());
                int[] positions = new int[9];
                Arrays.fill(positions, FormationEntity.POSITION_EMPTY);
                positions[7] = playerEntity.getId();
                formationEntity.setPositions(StringUtils.buildString(positions, ","));
                formationEntity.setMax(2); // TODO 阵形开放的关系，等神仙道多玩玩，在实现。找不到相关资料
                formationMapper.insert(formationEntity);
                createResult = 1;
            } catch (Exception e) {
                if (e.getCause() instanceof MySQLIntegrityConstraintViolationException
                        && e.getMessage().contains(PlayerEntity.DB_INDEX_UID_SERVERID)) {
                    createResult = 3;
                } else if (e.getCause() instanceof MySQLIntegrityConstraintViolationException
                        && e.getMessage().contains(PlayerEntity.DB_INDEX_SERVERID_NICKNAME)) {
                    createResult = 2;
                } else {
                    LOGGER.error("[doIo][{}] dao[{}] error[{}].", CommonErrorLogInfo.DB_OPERATE_FAIL, playerMapper, ExceptionUtils.getStackTrace(e));
                }
            }
        }
        return State.IO_DONE;
    }

    @Override
    public State doFinish() {
        if (online.isConnected()) {
            // 告诉客户端创建玩家结果
            online.write(new S_C_PlayerCreateResp(createResult));
            // 如果成功，则调用角色加载流程
            if (createResult == 1) {
                online.setState(OnlineState.client_create_roled); // 修改状态
                ioOperationService.asyncExecute(new PlayerLoadOperation(online));
            }
        }
        return State.FINISHED;
    }
}
